package com.leyou.order.service;

import com.leyou.ItemClient;
import com.leyou.common.auth.domain.UserHolder;
import com.leyou.common.exception.domain.ExceptionEnum;
import com.leyou.common.exception.domain.LyException;
import com.leyou.common.uploadimgs.LyConstants;
import com.leyou.common.utils.BeanHelper;
import com.leyou.common.utils.IdWorker;
import com.leyou.item.dto.SkuDTO;
import com.leyou.order.domain.Order;
import com.leyou.order.domain.OrderDetail;
import com.leyou.order.domain.OrderLogistics;
import com.leyou.order.dto.*;
import com.leyou.order.enums.OrderStatusEnum;
import com.leyou.order.mapper.OrderDetailMapper;
import com.leyou.order.mapper.OrderLogisticsMapper;
import com.leyou.order.mapper.OrderMapper;
import com.leyou.order.utils.PayHelper;
import com.leyou.user.client.UserClient;
import com.leyou.user.dto.AddressDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Slf4j
@Service
@Transactional
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderDetailMapper detailMapper;

    @Autowired
    private OrderLogisticsMapper logisticsMapper;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private ItemClient itemClient;

    @Autowired
    private UserClient userClient;
    @Autowired
    StringRedisTemplate redisTemplate;
    @Autowired
    PayHelper payHelper;

    /**
     * 保存订单
     * @param cartToOrderDTO
     * @return
     */
    public Long saveOrder(CartToOrderDTO cartToOrderDTO) {
        try {
            //获取到当前订单的id
            Long orderId = idWorker.nextId();
            //创建一个订单对象
            Order order = new Order();
            order.setOrderId(orderId);
            order.setStatus(OrderStatusEnum.INIT.value());
            order.setUserId(UserHolder.getUserId());
            order.setPaymentType(cartToOrderDTO.getPaymentType());
            order.setInvoiceType(0);
            order.setSourceType(2);
            order.setPromotionIds(null);
            order.setPostFee(0L);
            order.setActualFee(1L);
            //得到提交数据中的购物车对象
            List<CartDTO> carts = cartToOrderDTO.getCarts();
            //将集合类型的购物车对象转成map结构
            Map<Long, Integer> cartMap = carts.stream().collect(Collectors.toMap(CartDTO::getSkuId, CartDTO::getNum));
            //获取购物车对象中skuId的集合
            List<Long> skuIds = carts.stream().map(CartDTO::getSkuId).collect(Collectors.toList());
            //得到Sku对象集合
            List<SkuDTO> skuDTOS = itemClient.findSkusBySkuIds(skuIds);
            //计算总金额
            Long totalFee = skuDTOS.stream().mapToLong(sku -> sku.getPrice() * cartMap.get(sku.getId())).sum();
            order.setTotalFee(totalFee);
            //保存订单
            orderMapper.insertSelective(order);

            //获取一个订单详情的列表对象
            List<OrderDetail> detailList = new ArrayList<>();
            //遍历sku的集合
            skuDTOS.forEach(skuDTO -> {
                OrderDetail orderDetail = new OrderDetail();
                orderDetail.setId(idWorker.nextId());
                orderDetail.setOrderId(orderId);
                orderDetail.setSkuId(skuDTO.getId());
                orderDetail.setOwnSpec(skuDTO.getOwnSpec());
                orderDetail.setPrice(skuDTO.getPrice());
                orderDetail.setNum(cartMap.get(skuDTO.getId()));
                orderDetail.setTitle(skuDTO.getTitle());
                orderDetail.setImage(StringUtils.substringBefore(skuDTO.getImages(), ","));
                orderDetail.setCreateTime(new Date());
                orderDetail.setUpdateTime(new Date());
                detailList.add(orderDetail);
            });
            //保存订单详情
            detailMapper.insertList(detailList);

            //获取当前用户的地址
            AddressDTO addressDTO = userClient.queryAddressById(UserHolder.getUserId(), cartToOrderDTO.getAddressId());
            //将当用户的地址信息转成物流信息
            OrderLogistics orderLogistics = BeanHelper.copyProperties(addressDTO, OrderLogistics.class);
            orderLogistics.setOrderId(orderId);
            orderLogistics.setLogisticsNumber(String.valueOf(idWorker.nextId()));
            orderLogistics.setLogisticsCompany("菜鸟");
            //保存物流信息
            logisticsMapper.insertSelective(orderLogistics);

            //减库存
            itemClient.minusStock(cartMap);
            return orderId;
        }catch (Exception e){
            e.printStackTrace();
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }
    }

    /**
     * 查询订单
     * @param id
     * @return
     */
    public OrderDTO findOrderById(Long id) {
        //根据id查询订单对象
        Order order = orderMapper.selectByPrimaryKey(id);
        if(order==null){
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        //将pojo转成dto
        OrderDTO orderDTO = BeanHelper.copyProperties(order, OrderDTO.class);

        //根据订单id查询订单详情
        OrderDetail record = new OrderDetail();
        record.setOrderId(id);
        List<OrderDetail> orderDetails = detailMapper.select(record);
        if(CollectionUtils.isEmpty(orderDetails)){
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        //将pojo转成dto
        List<OrderDetailDTO> orderDetailDTOS = BeanHelper.copyWithCollection(orderDetails, OrderDetailDTO.class);
        orderDTO.setDetailList(orderDetailDTOS);

        //根据订单号查询物流信息
        OrderLogistics orderLogistics = logisticsMapper.selectByPrimaryKey(id);
        if(orderLogistics==null){
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        OrderLogisticsDTO orderLogisticsDTO = BeanHelper.copyProperties(orderLogistics, OrderLogisticsDTO.class);
        orderDTO.setLogistics(orderLogisticsDTO);

        return orderDTO;
    }


    /**
     * 微信支付生成二维码
     * @param id
     * @return
     */
    public String getPayUrl(Long id) {
        log.info("【统一下单】业务开始！");
        //获取当前订单在redis中存放支付链接的key值
        String payKey = LyConstants.ORDER_PAY_RUL_PRE+id;
        //从redis中查看是否有当前订单支付链接
        if(redisTemplate.hasKey(payKey)){
            log.info("【统一下单】业务成功！");
            //如果有，就直接取出并返回即可。
            return redisTemplate.opsForValue().get(payKey);
        }
        //根据订单查询订单对象
        Order order = orderMapper.selectByPrimaryKey(id);
        if(order==null){
            log.error("【统一下单】业务失败！订单不存在！");
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        if(order.getStatus()!=1){
            log.error("【统一下单】业务失败！订单已支付，不要重复支付！");
            throw new LyException(502, "订单已支付，不要重复支付！");
        }
        //调用统一支付下单获取支付链接
        String payUrl = payHelper.getPayUrl(id, order.getActualFee());
        //将当前支付链接放入redis，时长两个小时
        redisTemplate.opsForValue().set(payKey, payUrl, 2, TimeUnit.HOURS);
        log.info("【统一下单】业务成功！");
        return payUrl;
    }

    /**
     *  微信支付订单成功更新状态
     * @param id
     * @return
     */

    public Integer getPayCode(Long id) {
        Order order = orderMapper.selectByPrimaryKey(id);
        if(order==null){
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        return order.getStatus();
    }

    public void wxNotify(Map<String, String> notifyMap) {
        //验证微信的通信标识和业务标识
        payHelper.checkReturnAndResultCode(notifyMap);
        //获取订单号
        Long wxOrderId = Long.valueOf(notifyMap.get("out_trade_no"));
        //获取金额
        Long totalFee = Long.valueOf(notifyMap.get("total_fee"));
        //根据订单号查询订单
        Order order = orderMapper.selectByPrimaryKey(wxOrderId);
        if(order==null){
            throw new LyException(501, "【微信通知】异常！订单不存在！");
        }
        if(!totalFee.equals(order.getActualFee())){
            throw new LyException(501, "【微信通知】异常！金额不对！");
        }
        if(order.getStatus()!=1){
            log.info("【微信通知】订单已支付！");
        }
        //更新订单状态
        Order record = new Order();
        record.setOrderId(wxOrderId);
        record.setStatus(OrderStatusEnum.PAY_UP.value());
        int count = orderMapper.updateByPrimaryKeySelective(record);
        if(count!=1){
            //应该将异常订单入库，在后台手动处理。
            log.info("【微信通知】修改订单状态异常！");
        }
    }
}